#!/usr/bin/env python3
# -*- coding: utf-8 -*-


import struct
import zlib
from fontTools.ttLib import TTFont
from PIL import Image, ImageDraw, ImageFont
import pytesseract
import numpy
import os


import logging
import traceback


def woff_to_tff(woff_file, tff_file):
    woff_fp = None
    tff_fp = None
    try:
        woff_fp = open(woff_file, mode='rb')
        tff_fp = open(tff_file, mode='wb')
        woff_header = {
            'signature': struct.unpack(">I", woff_fp.read(4))[0],
            'flavor': struct.unpack(">I", woff_fp.read(4))[0],
            'length': struct.unpack(">I", woff_fp.read(4))[0],
            'numTables': struct.unpack(">H", woff_fp.read(2))[0],
            'reserved': struct.unpack(">H", woff_fp.read(2))[0],
            'totalSfntSize': struct.unpack(">I", woff_fp.read(4))[0],
            'majorVersion': struct.unpack(">H", woff_fp.read(2))[0],
            'minorVersion': struct.unpack(">H", woff_fp.read(2))[0],
            'metaOffset': struct.unpack(">I", woff_fp.read(4))[0],
            'metaLength': struct.unpack(">I", woff_fp.read(4))[0],
            'metaOrigLength': struct.unpack(">I", woff_fp.read(4))[0],
            'privOffset': struct.unpack(">I", woff_fp.read(4))[0],
            'privLength': struct.unpack(">I", woff_fp.read(4))[0]
        }

        tff_fp.write(struct.pack(">I", woff_header['flavor']))
        tff_fp.write(struct.pack(">H", woff_header['numTables']))
        maximum = list(filter(lambda x: x[1] <= woff_header['numTables'], [(n, 2 ** n) for n in range(64)]))[-1]
        search_range = maximum[1] * 16
        tff_fp.write(struct.pack(">H", search_range))
        entry_selector = maximum[0]
        tff_fp.write(struct.pack(">H", entry_selector))
        range_shift = woff_header['numTables'] * 16 - search_range
        tff_fp.write(struct.pack(">H", range_shift))

        offset = tff_fp.tell()

        table_directory_entries = []
        for i in range(0, woff_header['numTables']):
            table_directory_entries.append({
                'tag': struct.unpack(">I", woff_fp.read(4))[0],
                'offset': struct.unpack(">I", woff_fp.read(4))[0],
                'compLength': struct.unpack(">I", woff_fp.read(4))[0],
                'origLength': struct.unpack(">I", woff_fp.read(4))[0],
                'origChecksum': struct.unpack(">I", woff_fp.read(4))[0]
            })
            offset += 4 * 4

        for table_directory_entry in table_directory_entries:
            tff_fp.write(struct.pack(">I", table_directory_entry['tag']))
            tff_fp.write(struct.pack(">I", table_directory_entry['origChecksum']))
            tff_fp.write(struct.pack(">I", offset))
            tff_fp.write(struct.pack(">I", table_directory_entry['origLength']))
            table_directory_entry['outOffset'] = offset
            offset += table_directory_entry['origLength']
            if (offset % 4) != 0:
                offset += 4 - (offset % 4)

        for table_directory_entry in table_directory_entries:
            woff_fp.seek(table_directory_entry['offset'])
            compressed_data = woff_fp.read(table_directory_entry['compLength'])
            if table_directory_entry['compLength'] != table_directory_entry['origLength']:
                uncompressed_data = zlib.decompress(compressed_data)
            else:
                uncompressed_data = compressed_data
            tff_fp.seek(table_directory_entry['outOffset'])
            tff_fp.write(uncompressed_data)
            offset = table_directory_entry['outOffset'] + table_directory_entry['origLength']
            padding = 0
            if (offset % 4) != 0:
                padding = 4 - (offset % 4)
            tff_fp.write(bytearray(padding))
    except Exception as e:
        logging.error(e)
        logging.error(traceback.format_exc())
    finally:
        if woff_fp is not None:
            woff_fp.close()
        if tff_fp is not None:
            tff_fp.close()


def ttf_to_dic(ttf_file):
    fonts = TTFont(ttf_file)
    code_list = fonts.getGlyphOrder()[2:]
    im = Image.new("RGB", (1800, 1000), (255, 255, 255))
    dr = ImageDraw.Draw(im)
    font = ImageFont.truetype(font=os.path.abspath(ttf_file), size=40)
    count = 18
    array_list = numpy.array_split(code_list, count)
    for t in range(count):
        new_list = [i.replace("uni", "\\u") for i in array_list[t]]
        text = ''.join(new_list)
        text = text.encode('utf-8').decode('unicode_escape')
        dr.text((0, 50 * t), text, font=font, fill="#000000")
    # 不保存文件, 识别更精准
    # im.save(font_jpg_file)
    # im = Image.open(font_jpg_file)
    result = pytesseract.image_to_string(im, lang="chi_sim")
    result = result.replace(" ", "").replace("\n", "")

    # 对于识别结果，常进行一些替换操作
    rep = {'O': '0', 'I': '1', 'L': '1', 'Z': '2', 'S': '8'}
    for r in rep:
        result = result.replace(r, rep[r])
    code_list = [i.replace("uni", "&#x") + ";" for i in code_list]
    return dict(zip(code_list, list(result)))
